package base

import (
	"context"
	"gitee.com/bobo-rs/innovideo-services/framework/model"
	"gitee.com/bobo-rs/innovideo-services/library/exception"
	"github.com/gogf/gf/v2/frame/g"
)

// ListAndTotal 获取数据列表和数量
func (s *TblBaseService) ListAndTotal(ctx context.Context, in model.CommonListAndTotalInput, pointer interface{}, total *int) error {
	err := s.WhereErr(in.Where)
	if err != nil {
		return err
	}
	// 查询数据
	return g.Model(s.Table).
		Ctx(ctx).
		Where(in.Where).
		Page(in.Page, in.Size).
		Order(in.Sort).
		ScanAndCount(pointer, total, true)
}

// Scan 获取并扫描数据
func (s *TblBaseService) Scan(ctx context.Context, where, pointer interface{}) error {
	err := s.WhereErr(where)
	if err != nil {
		return err
	}
	return g.Model(s.Table).Ctx(ctx).Where(where).Scan(pointer)
}

// ScanOmitEmpty 过滤条件为空并获取数据
func (s *TblBaseService) ScanOmitEmpty(ctx context.Context, where, pointer interface{}) error {
	err := s.WhereErr(where)
	if err != nil {
		return err
	}
	return g.Model(s.Table).
		Ctx(ctx).
		OmitEmpty().
		Where(where).
		Scan(pointer)
}

// DetailPri 通过主键ID获取详情
func (s *TblBaseService) DetailPri(ctx context.Context, id uint, pointer interface{}) error {
	if id == 0 {
		return exception.New(`缺少主键ID`)
	}
	err := g.Model(s.Table).
		Ctx(ctx).
		WherePri(id).
		Scan(pointer)
	if err != nil {
		return exception.New(`暂无数据`)
	}
	return nil
}

// Total 获取数据总数
func (s *TblBaseService) Total(ctx context.Context, where interface{}) (int, error) {
	err := s.WhereErr(where)
	if err != nil {
		return 0, err
	}
	return g.Model(s.Table).Ctx(ctx).Where(where).Count()
}

// Exists 检测数据是否存在
func (s *TblBaseService) Exists(ctx context.Context, where interface{}) (bool, error) {
	total, err := s.Total(ctx, where)
	if err != nil {
		return false, err
	}
	return total > 0, nil
}

// Save 更新数据-基础操作
func (s *TblBaseService) Save(ctx context.Context, data interface{}) error {
	// 更新数据
	_, err := g.Model(s.Table).
		Ctx(ctx).
		OmitEmpty().
		Save(data)
	if err != nil {
		return exception.New(`保存失败，请重试`)
	}
	return nil
}

// Update 更新数据-简单操作
func (s *TblBaseService) Update(ctx context.Context, where, data interface{}) error {
	if s.WhereErr(where) != nil || s.WhereErr(data) != nil {
		return exception.New(`缺少参数`)
	}
	// 更新数据
	_, err := g.Model(s.Table).
		Ctx(ctx).
		Where(where).
		Data(data).
		Update()
	if err != nil {
		return exception.New(`更新失败，请重试`)
	}
	return nil
}

// UpdatePri 根据主键ID更新数据(唯一主键有效)
func (s *TblBaseService) UpdatePri(ctx context.Context, id uint, column string, value interface{}) error {
	if id == 0 {
		return exception.New(`主键ID不能为空`)
	}
	_, err := g.Model(s.Table).
		Ctx(ctx).
		WherePri(id).
		Data(column, value).
		Update()
	if err != nil {
		return exception.New(`更新失败，请重试`)
	}
	return nil
}

// DeletePri 根据主键ID删除数据（唯一主键有效）
func (s *TblBaseService) DeletePri(ctx context.Context, id uint) error {
	if id == 0 {
		return exception.New(`主键ID不能为空`)
	}

	// 检测需要删除数据是否存在
	orm := g.Model(s.Table).Ctx(ctx).WherePri(id)
	if total, _ := orm.Count(); total == 0 {
		return exception.New(`数据不存在或已删除`)
	}

	// 删除数据
	_, err := orm.Delete()
	if err != nil {
		return exception.New(`删除失败，请重试`)
	}
	return nil
}

// Delete 删除数据
func (s *TblBaseService) Delete(ctx context.Context, where interface{}) error {
	err := s.WhereErr(where)
	if err != nil {
		return err
	}

	// 检测需要删除数据是否存在
	if total, _ := s.Total(ctx, where); total == 0 {
		return exception.New(`数据不存在或已删除`)
	}

	// 删除数据
	_, err = g.Model(s.Table).
		Ctx(ctx).
		Where(where).
		Delete()
	if err != nil {
		return exception.New(`删除失败，请重试`)
	}
	return nil
}

// TotalPri 通过主键ID获取数据总数
func (s *TblBaseService) TotalPri(ctx context.Context, id ...uint) (int, error) {
	if len(id) == 0 || (len(id) > 0 && id[0] == 0) {
		return 0, exception.New(`主键ID不能为空`)
	}
	return g.Model(s.Table).Ctx(ctx).WherePri(id).Count()
}

// ExistsPri 通过主键ID检测数据是否存在
func (s *TblBaseService) ExistsPri(ctx context.Context, id uint) (bool, error) {
	total, err := s.TotalPri(ctx, id)
	return total > 0, err
}
